#coding=utf-8

module Aio::Module
  class Cmd

    include Aio::Ui::Verbose

    class MethodError < StandardError
      def to_s; "请重载此方法"; end
    end

    class MismatchError < StandardError; end

    autoload :Ranking, 'aio/module/ranking'
    autoload :Platform, 'aio/module/platform'

    # 加载的欲解析的文本
    attr_accessor :context

    # 模块的信息
    attr_accessor :cmd_info

    # 解析后得到的有用信息
    # 以Hash = { :case => info }
    attr_accessor :useful

    # 加载warning信息
    attr_accessor :warning_klass

    # 加载设备的基本信息
    # :device_version
    # :device_model
    attr_accessor :device_info

    # 获取一些额外的信息，有device提供
    attr_accessor :ext_info

    def initialize(info = {})
      @cmd_info = info.dup
      @useful = {}
      set_defaults()
    end

    # 将自己分裂出来一份,以免遭到覆盖
    def division
      self.class.new
    end

    def set_defaults
      self.cmd_info = {
        :cmd_full		=> 'No full name',
        :cmd_short 	=> 'No short name',
        :author			=> nil,
        :description => 'No command description',
        :ranking		=> Ranking_1,
        # 用于确定设备类型
        :key_stand	=> false,
        :benchmark  => {},
        # 平台，是 route, switch 还是 failware
        :platform		=> nil,
        :license		=> Aio::AIO_LICENSE,
      }.update(@cmd_info)
    end

    def type
      Aio::Module::Cmd
    end

    def clear_useful
      @useful = {}
    end

    # 所有Cmd模块都必须重载此方法，用于解析命令
    def parse
      raise MethodError.new
    end

    def cmd_full;	 self.cmd_info[:cmd_full]; 	end
    def cmd_short; self.cmd_info[:cmd_short]; end
    def author;		 self.cmd_info[:author];		end
    def description;	self.cmd_info[:description];	end
    def ranking;	 self.cmd_info[:ranking];		end
    def benchmark; self.cmd_info[:benchmark]; end
    def platform;	 self.cmd_info[:platform];	end
    def license;	 self.cmd_info[:license];		end
    def key_stand; self.cmd_info[:key_stand];		end

    protected

    # 直接调用平级CMD模块
    def call_cmd(cmd_constant)
      begin
        cmd_klass = cmd_constant.new
        cmd_klass.useful = @useful
        cmd_klass.context = @context
        cmd_klass.warning_klass = @warning_klass
      rescue Exception
        print_error "<call_cmd> 方法调用失败: #{cmd_constant}"
      end
      cmd_klass.parse
    end

    def key_stand_cisco
      useful[:device_type] = "cisco"
    end

    def key_stand_huawei
      useful[:device_type] = "huawei"
    end

    def key_stand_h3c
      useful[:device_type] = "h3c"
    end

    def key_stand_maipu
      useful[:device_type] = "maipu"
    end

    def key_stand_juniper
      useful[:device_type] = "juniper"
    end

    # 确定软件版本
    def key_stand_version(ver)
      useful[:device_version] = ver
    end

    def device_version
      device_info[:device_version]
    end

    # 确定设备型号
    def key_stand_model(model)
      useful[:device_model] = model
    end

    def device_model
      device_info[:device_model]
    end

    def key_stand_template(template)
      begin
        template.instance
      rescue
        raise RuntimeError, "请使用Template类" 
      end
      useful[:device_template] = template.to_s
    end

    def device_template
      Object::const_get(device_info[:device_template]).instance
    end

    def reg_blank
      Aio::Base::Toolkit::Regexp.blank
    end

    def reg_separator
      if self.kind_of?(Cisco)
        return /^!$/
      elsif self.kind_of?(H3C)
        return /^[#]$/
      else
        reg_blank
      end
    end

  end
end

class Aio::Module::Cmd::Cisco < Aio::Module::Cmd; end
class Aio::Module::Cmd::Huawei < Aio::Module::Cmd; end
class Aio::Module::Cmd::H3C < Aio::Module::Cmd; end
class Aio::Module::Cmd::Maipu < Aio::Module::Cmd; end
class Aio::Module::Cmd::Juniper < Aio::Module::Cmd; end
